so I got this in my Main class:
public class Main extends JFrame {
public static void main(String[] args) {
JFrame Launch = new JFrame();
Launch.setSize(800, 400);
Launch.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Launch.setContentPane(new StartView());
Launch.setTitle("De Hartige Hap");
Launch.setVisible(true);
}
}
Now let's say I'm in that Panel ("StartView()")
and onClick on a button, I want to change the frames' contentpane..
How would I do this?
public class StartView extends javax.swing.JPanel {
public StartView() {
initComponents();
}
private void OrderButtonActionPerformed(java.awt.event.ActionEvent evt) {
/*instead of Launch.setContentPane(new StartView());
*it has to be (new otherView())
*/
}
Pass your Launch object to your panel object (i.e. new StartView(launch)). This way, you can create a method changeView() in Launch and you can call this method from your panel (launch.changeView()), you can change your view inside that method.
Also, if I may adivce you, take a look at the ModelViewController pattern. This makes sure you keep the View (your panels) and the Controller (your Frame) seperated so you don't get issues like this.
Related
I am trying to implement mouse listener however I can not seem to get it to work. My code doesnt have any errors, but when I click on the frame I I can not get a message to print out. I have tried extending the class HandleClassOne to viewOne, but that also wouldn't work. Any thoughts?
The main class creates a frame and then creates an instance of viewOne on the frame.
public class main{
protected static JFrame window;
public static void main(String args[]){
window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(400,400);
window.setVisible(true);
new viewOne(window);
}
}
The viewOne class adds a panel and a label to a frame. It also adds a mouse listener to the panel.
public class viewOne {
private static JPanel panel1;
private static JLabel label1;
public viewOne(JFrame frame) {
panel1 = new JPanel();
label1 = new JLabel("View One");
panel1.add(label1);
frame.add(panel1);
panel1.setBackground(Color.red);
frame.validate();
}
public static void mouseAdd() {
HandleClassOne handle = new HandleClassOne();
panel1.addMouseListener(handle);
panel1.addMouseMotionListener(handle);
}
public static void main(String[] args) {
mouseAdd();
}
}
The HandleClassOne class should print out a message when the panel created in viewOne is clicked.
public class HandleClassOne extends main implements MouseListener, MouseMotionListener {
public void mouseClicked(MouseEvent e) {
System.out.println("mouse clicked");
}
}
While you have defined the function mouseAdd(...) I don't see you calling it.
Try (within the constructor)
public viewOne(JFrame frame) {
...
mouseAdd();
...
}
naturally, you'll need to do this after the panel1 is set.
Note that there are other issues, too
You don't invoke presenting the JFrame properly within your main function in your main class. Look up a basic tutorial on Java Swing, where it talks about the event dispatch thread and the requirements to not present within your program's main thread of execution.
You have an additional main function in your viewOne class, which is not how these things are wired up.
You added the mouseAdd() method (which is responsible for registering the mouse listener) inside the main method of viewOne class.
Please keep in mind that main method only gets called whenever you are running it as entry point class for your application. Here you have main class to act as an entry point.
You kept main method in viewOne class as well and it will get called only when you are running it as an individual piece (not along with main class).
To fix the issue here, keep your mouseAdd() method call inside viewOne() constructor as constructor gets called every time whenever object is getting created.
public viewOne(JFrame frame) {
panel1 = new JPanel();
label1 = new JLabel("View One");
panel1.add(label1);
frame.add(panel1);
panel1.setBackground(Color.red);
mouseAdd();
frame.validate();
}
I have a jframe object in a class and I want to be able to close the frame from my jpanel class(which obviously I attach to the frame). Anyway, I tried making a instance field in my jpanel with the jframe object has an instance field and then made a method that I would call in the jframe class with the parameter of the jframe object I made so I could make the jpanel instance field the same object as the jframe object. I then called the instance field.dispose(); hoping it would close the frame. Any ideas would be greatly appreciated!
In case that was hard to understand here is an example:
public class example extends jFrame
{
public static void main(String[]args)
{
examplePanel ep = new examplePanel();
example e = new example(ep);
}
/**
* Constructor for objects of class example
*/
public example(examplePanel ep)
{
//code that handles my frame settings
}
}
public class examplePanel extends jPanel implements ActionListener
{
private example e;
private boolean checkWin;
public void actionPerformed(ActionEvent e)
{
if(this.checkWin())
{
setVisible(false);
e.dispose();
//^this line of code is supposed to dispose of the frame but it does not
}
}
public void getExample(example e)
{
this.e = e;
}
}
Your code and question are hard to follow as you have an ActionListener which you add to no JButton or JMenuItem, You create a JFrame object and a JPanel, but are never observed to add the panel to the frame. You give your JPanel an "example" variable, but never assign it a reference to the visualized JFrame, you don't appear to ever set the default close operation of the JFrame, and so your JFrame as written above should be non-closable. From your code it looks like your examplePanel's e variable in the JPanel should in fact be null and so calling any method on it should throw a NullPointerException, that is unless you're assigning the correct JFrame object reference to it, but are not showing us.
Myself, I'd get the top level window from Swing itself when needed, something like:
#Override
public void actionPerformed(ActionEvent e) {
// get the top-level window that is displaying this JPanel
Window win = SwingUtilities.getWindowAncestor(this);
if (win != null) {
win.dispose(); // dispose of it
}
}
For example:
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.*;
import javax.swing.*;
public class CloseFromJPanel extends JPanel implements ActionListener {
private static final int PREF_W = 400;
private static final int PREF_H = 300;
public CloseFromJPanel() {
JButton closeButton = new JButton("Close Me");
closeButton.addActionListener(this);
add(closeButton);
}
#Override
public void actionPerformed(ActionEvent e) {
// get the top-level window that is displaying this JPanel
Window win = SwingUtilities.getWindowAncestor(this);
if (win != null) {
win.dispose(); // dispose of it
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Close From JPanel");
// GUI will exit when the JFrame is closed
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new CloseFromJPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
This code will work for JButtons within JFrames and JDialogs, but not JMenuItems or within JApplets (I don't think). Or if all you want to do is end the application, then you could simply call System.exit(0) from within the actionPerformed method. If you absolutely want to do this using a field of the JFrame, then you'll need to pass in a reference to the JFrame into the JPanel, likely using a constructor parameter, and possibly passing in this.
If this doesn't help, please create and post real code, not kind-of sort-of code, code that we can compile, run and actually test, an MCVE (please check out the link).
Other issues:
Your code does not comply with Java naming standards as class names should all start with capital letters. Please Google this and study it, since if your code follows standards, others, including both us and your future self, will better be able to understand your code.
You'll rarely want to ever extend from JFrame since you rarely need to alter it's innate behavior. Usually you'll create and use a JFrame or JDialog when and where needed.
I'm kind of confused. I'm at work right now (just started apprenticeship) and need to create a fully editable table (I'll use SQL soon). So I have 2 questions here:
What do you mean by "Don't extend JFrame"? Let's say I have a class called "TestDialog" and also a JFrame which is called "TestUI". Would it be okay to write
public class TestDialog extends TestUI ?
As I have understood it, one shouldn't create a class (called MyExample) and inside of this class just write
public class MyExample extends JFrame
Because you create a JFrame within an existing class instead of creating it seperate.
I'll keep it short - Can I use 2 actions in 1 listener (for 1 button)? Something like:
public void actionPerformed(ActionEvent e)
{
Action_One; Action_Two;
}
Or do I need to use 2 different listeners?
Okay that's it I guess. I'm sorry that I haven't written everything clearly, I just registered here and actually concentrate on translating things from my language into english. If anyone could tell me how to write here like in Eclipse I'd appreciate it, because I couldn't really find out how.
Composition over inheritance is an important programming approach. So I preffer following construction of GUI.
public class Application {
private JFrame mainFrame;
private MainPanel mainPanel;
private void installFrame() {
// initialize main frame
mainFrame = new JFrame("Title");
}
private void installComponents() {
// install all components
mainPanel = new MainPanel();
}
private void layout() {
// provide layouting
mainFrame.add(mainPanel.getComponent());
}
private void show() {
mainFrame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Application app = new Application();
app.installFrame();
app.installComponents();
app.layout();
app.show();
}
});
}
}
Main panel has no inheritance from JPanel, but use an instance of it.
public class MainPanel {
private JPanel mainPanel;
public MainPanel() {
mainPanel = new JPanel(new GridBagLayout()); // or another layout
initComponents();
layout();
}
private void initComponents() {
// init all components here
}
private void layout() {
// layout panel here
}
public Component getComponent() {
return mainPanel;
}
}
The same pattern I use for each complex component (for example for trees, tables, lists, tabbed panes etc.). But this approach has one disadvantage: there is no GUI builder that support it.
About actions: you can provide a combined action. Something like this
public class CombinedAction extends AbstractAction {
private Action[] delegates;
public CombinedAction(String name, Icon icon, Action... someDelegates) {
super(name, icon);
delegates = someDelegates;
}
public void actionPerformed(ActionEvent ae) {
for (Action delegate : delegates) {
delegate.actionPerfromed(ae);
}
}
}
What do you mean 2 actions? You can do anything in the actionPerformed() method. If instead your question is "can I have 2 actionPerformed methods in the class" ie two actionListeners then it's a 'NO'. You must instead read on Inner Classes to do that.
And regarding your first question it's more of a design issue.
I would prefer
public class Example{
JFrame frame;
public void initialize()
{
frame.setSize(//params);
frame......
//other frame initilizing code
}
public static void main(string[] args)
{
Example example=new Example();
example.initialize();
}
}//class ends
while someone else may feel otherwise
I have this class for my UI
public class MyFrame extends JFrame{
JTextArea textArea;
public MyFrame(){
setSize(100,100);
textArea = new JTextArea(50,50);
Container content = getContentPane();
content.add(textArea);
}
public static void main(String[] args){
JFrame frame = new MyFrame();
frame.show();
UpdateText u = new UpdateText();
u.settext("Helloworld");
}
}
And I have this another class that will set the text of textArea, in which I extended MyFrame to access textArea in another class.
public class UpdateText extends MyFrame{
public void settext(String msg){
textArea.setText(msg);
}
}
Then I instantiate UpdateText and call the function settext. but the text doesn't seem to appear in the GUI.
First of all, don't override the setText() method unless you want different behavior. Second of all, you don't have to extend anything. All you have to do is follow these simple steps and you'll be set!
In the UpdateText class, put these lines somewhere in it:
MyFrame gui;
public UpdateText(MyFrame in) {
gui = in;
}
In the 'MyFrame` class, put this line at the beginning:
UpdateText ut = new UpdateText(this);
Now, you can refer to everything in the MyFrame class from the UpdateText class by preceeding what you want to change with gui. For example, say you wanted to change the text of your textarea. The code would be the following:
gui.textArea.setText("Works!");
Happy coding! :)
I have a button in a JFrame, if pressed, it takes us to another frame.
I used this code:
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
SecondForm secondform = new SecondForm();
secondform.setVisible(true);
setVisible(false);
dispose();
}
So the new frame opens and everything is ok. Then i placed another button -in the second frame- in order to go back to the previous frame. I used this code:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
MainForm Mform = new MainForm();
Mform.setVisible(true);
setVisible(false);
dispose();
}
The thing is, i don't think this is the right way to do this. What i want is to:
hide the first frame
show the new second one
dispose the second one
show again the first
Is there a way to do that using the first MainForm instance and not creating a new one every time i want to go back.
I monitored my program and every time i go back and forth the frames and as i suspected, the ram being used by it keeps increasing.
Thanks in advance.
EDIT : I have a login system and when the user put the correct credentials a new ManiForm instance is created.
MainForm Mform = new MainForm();
Mform.setVisible(true);
That is the instance i want to use. Ii there a way to make MForm visible again from the secondform?
First of all thanks for the help!
I agree that it is easier not to use more than one JFrames, but can you please tell me which is the better way to do what i asked in the first post?
The answer Robin gave me is very nice but i don't know what to put as an argument there*:
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
* new SecondForm().setVisible(true);
}
});
It's from the auto-generated code from NetBeans.
I tried
new SecondForm(super).setVisible(true);
but i still get compile errors. Apparently i must put super.something() but i don't know what. I tried many but no luck.
you shouldn't use more then one frame.
You should have NOTHING in JFrame except defaultExitOperation, size, preferedsize and visible true.
Instead place all buttons and fields into a JPanel and add/remove the JPanel from the JFrame.
If you want another Window open use JDialog.
btw: you can have your MainFrame setVisible false and open a JDialog with your MainFrame as parent. Only if someone writes down the right user + password you make the MainFrame visible.
For swing applications, the standard is to use a STATIC MAIN FRAME, in other words, make your main frame (mframe) static and add methods to pop-up new frames, dialogs, optionPanes, etc. You can even control the visibility of the main frame throw static calls. That's the way you implement a UNIQUE FRAME for your application, even tho you instance other frames for navigation, all child frames can refer to the main frame without the need of passing it as parameter to constructors or creating new instances of it.
The Main Class
`/* to start the application */
public class Main{
public static MainFrame MFRAME;
public static void main(String[] args){
/*use this for thread safe*/
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Main.MFRAME = new MainFrame(/*init parms to constructor*/);
}
});
}
}
`
The Main Frame
`/* to create the main frame */
public class MainFrame extends JFrame{
public MainFrame(/*your constructor parms*/){
/* constructor implementation */
}
public void openOtherFrame(/*your parms*/){
OtherFrame oFrm = new OtherFrame(/*your parms*/);
}
/* other methods implementation */
}
`
The child frame
`/* to open child frames controling the visibility of the main frame*/
public class OtherFrame extends JFrame{
public OtherFrame(/*your constructor parms*/){
/* hide main frame and show this one*/
Main.MFRAME.setVisible(false);
this.setVilible(true);
/* do something else */
/* show main frame and dispose this one*/
Main.MFRAME.setVisible(true);
this.dispose();
}
/* other methods implementation */
}
`
If you pass your MainForm to the SecondForm class (for example using a constructor parameter) the SecondForm instance can make the original MainForm instance visible again instead of creating a new one.
For example
public class SecondForm extends JFrame{
private final MainForm mainForm;
public SecondForm( MainForm form ){
mainForm = form;
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
mainForm.setVisible(true);
setVisible(false);
dispose();
}
}
and in your MainForm class
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
SecondForm secondform = new SecondForm( this );
secondform.setVisible(true);
setVisible(false);
dispose();
}