I'm taking a beginning Java class and an assignment requires that I write a class to represent a JPanel with buttons to increment and decrement a value and a label to display the value. Then, I have to create a separate class which instantiates the panel and adds it to a frame. I'm trying to have the frame resize to fit the size of the panel by running the pack method. I try to call the frame's pack method by using:
SwingUtilities.getAncestorOfClass(JFrame.class, this).pack()
I get a "cannot find symbol - method pack()" error. The getAncestorOfClass is definitely returning a JFrame, and it is the correct JFrame. When I run the pack method from inside the driver class where the JFrame is created, there are no problems. Any ideas why it can't find the pack method? Is it because I'm trying to run this from a separate class file? I also can't access some other JFrame methods such as getContentPane, but I am able to access some others such as add. Huh?
The method SwingUtilities.getAncestorOfClass returns a Container. Now, you know that Container is really gonna be a JFrame, but the compiler doesn't. And Java is a static language, not a dynamic one that'll just try to call the method regardless of whether the class declares it or not.
Since Container doesn't have pack method, the compiler's gonna complain. You'll need to cast to JFrame to make it work:
((JFrame)SwingUtilities.getAncestorOfClass(JFrame.class, this)).pack();
Careful, though... The method can return null if no suitable ancestor was found. You might want to check that first.
You need to cast it to JFrame:
((JFrame) SwingUtilities.getAncestorOfClass(JFrame.class, this)).pack();
The SwingUtilities.getAncestorOfClass(Class, Component) method return a component, and not a JFrame.
Related
I am new to stackoverflow and am sorry, if this question was already asked, but when I searched for one containing my problem, I could not find one.
Here is my question:
In Java I am creating a game (just for fun and am learning to code). You start my game with a launcher to log in. However, if you do not have an account, you can register. What I like more is to use one frame. I have a panel containing the launcher elements and one containing the register elements. I am trying to learn how to code, if another one is working on my project, he does not necessarily need to look all over the code to do some work. In other words, I am using packages to sort classes. Example: Classes for the launcher are in package Launcher. Classes for register are in package register.
In my code, I have a class called Display extending JFrame. Display is instanciated in the class with the main method. Display has 2 Methods for removing a panel and adding a panel, requiring you to pass a JPanel, if you use any of both methods. After Display is instantiated, it instantiates a jpanel inside the constructor. This has all the components to Display. The event listeners are in another class. So I am passing the buttons and Display to that class, because here is the eventlistener code for the button register. In my register class I have defined and instantiated all necessary components. I passed the display through all of the classes until it reached the register class which extends jpanel. I even passed the Launcher class. Now i can use the methods in display to remove the launcher panel and add my register panel.
My Question:
is this good code or overkill?
I never instantiated Display after the main method again. I always declared it and set it to the passed display. I did this, because instantiated a new Display would mean unnecessary use of memory and passing objects in java is actually a passing by references, meaning it is not passing the object but a pointer to the object. So this would mean less memory usage.
I've got a class in which there is a method that draws rectangles on a JFrame. Furthermore I've got a few methods with different types of sorting. In those sorting methods I am calling the drawing method when a specified button is clicked. I would like my code to be cleaner, so I wanted to divide the class into one that is responsible for drawing things and the other one that does the sorting. I don't know how I can call the drawing method from outside the class. I wanted to use static, but I would have to make all the variables inside the method static. I also thought about making an inner class, but I will still have that one big class and it doesn't really help. What can I do?
You should only be drawing from within the paintComponents method of the container. So it doesn't make sense for some external code to initiate a call to draw stuff. If you want this external class to change what is drawn, it should pass a reference to an object implementing some understood interface that can be called by the paintComponents method.
I am working on a project for a CS class, so I cannot post any code, but I will try my best to describe what setup I have. The program is supposed to have 3 separate JPanels, each with an image and buttons to rotate and reset the image. A Driver class was provided that sets up the JFrame, creates a single Project object to pass around to other classes (this Project class contains the methods for rotating and combining the images), and has the main method.
What I've done is create a class that extends JPanel to setup a JPanel with the image, file name, and rotate/reset buttons. I have the constructor for this class taking in the number of the panel (to keep up with writing the image number in the panel), the image file to display, and the Project object that was created in the Driver class (to be able to access the methods for manipulating the images). I immediately call super(); and then set up the file name and image (as a JLabel) and buttons as (JButtons).
This is where my problem comes in though. I'm trying to set up the Rotate button, so I created an anonymous inner class action listener and actionPerformed method. What I planned on doing was using the Project object reference to call the rotate method on the image object, having it return a BufferedImage into a modifiedImage BufferedImage. Then remove the JLabel with the original image, add the modifiedImage as a JLabel, revalidate, and repaint. However, I cannot use the this reference or the reference to the Project object within the inner actionPerformed class.
How do I gain access to these references within the actionperformed inner class? or is my setup completely awful? Please bear with me- it's my first time working with any kind of GUI.
Make your reference to Project object final. It will solve the problem and does not make any harm as you are not going to assign it again.
I've been working on a Java Swing project where I need to retrieve the object/instance that created a panel in order to call a simple save method particular to that instance.
You have a JFrame with a JTabbedPane that has tabs created by instancing a class which builds a JPanel and adds it to the JTabbedPane, I need to find the specific instance from the selected JPanel/tab on the JTabbedPane to then call it's save method.
Any ideas?
Thanks for your time!
public class frame extends JFrame implements ActionListener{
Builds a frame dubbed "frame" that is static.
Builds a static JTabbedPane dubbed "pane"and adds it to the frame.
Creates a button that creates a new instance of sheet.
public void actionPerformed(MAGIC!){
See if a button on the panel has been pressed and uses the currently selected tab to locate the correct instance of sheet to run it's save method.
}
}
public class sheet extends JPanel{
In constructor makes a JPanel and adds it to "pane"
Describes a save method that outputs a variable unique to the instance.
}
I figured out all I needed to do was store new tab objects in an ArrayList derp. Thanks for your attempts though guys!
Rather than just connecting back to the original creator, my approach to this was to create / use an interface that expicitly supports saving. I created something for this in TUS, my sourceforge project
http://tus.svn.sourceforge.net/viewvc/tus/tjacobs/io/filepersist/
Check out Persistable and Persistable2. Of course anything can be a Persistable, but the abstraction let's you get away from explicit ties back to the creator class
You can add a field in the new JPanels that point to the instance of the creator. I don't think there is any such method to point back to parent class in the API.
--EDIT--
You may want to check
http://docs.oracle.com/javase/tutorial/uiswing/components/tabbedpane.html
getSelectedIndex() may be what you are looking for.
After some advice on using jpanel - I'm new to java and playing around with the GUI elements.
Bascially what I'm curious about is if I can set up a Jpanel in one class, then somehow add labels etc to the that container, but from another class.
Is this possible ? or do i have to set the entire GUI up in one class, but then I guess I would have the same issue, if I wanted to update those fields I had set up in the main class from another class?
Apologies I don't really have any code that's usefull to demostrate here - I'm just trying to get the idea going, working out if its possible before I go ahead. And I'm not even sure if this is possible. Any advice would be greatly appreciated.
Thanks
As long as you have a reference to the JPanel, you can add whatever GUI-element you want, by calling add(JComponent comp) on the JPanel.
So, you can do something like this:
class Panel extends JPanel{
...
}
class Main{
public Main(JPanel thePanel){
thePanel.add(new JButton("Hello"));
}
}
Was this what you were looking for?
You can also update the fields added to the panel from another class, if you have a public accessor-method set up, in the class. So in your panel class, you have a method:
public JButton getButton(){
return button;
}
Then you can access the button from whatever class with a reference to your panel class, like this:
panel.getButton().setText("Some text");
Note that the button could just as well be public, then you could simply call the method directly: panel.button.setText("Some text"); but this is not considered good code, as it violates some general good OOP practices, not relevant to mention here.