Am I able to override a method on demand? I have a class that extends JFrame and has a JPanel inside. I want to draw a circle in the JPanel but I don't want to have an own class for the JPanel (then I could override paintComponent). My idea was something like this:
public class KugelClient extends JFrame {
public KugelClient() {
super("KugelClient");
JPanel panel = new JPanel();
panel.paintComponent(Graphics g) {
//overriding method here
g.fillOval(...);
}
}
Is there anything in Java which makes it possible to do something like this (e.g. with lambda?) or do I have do create an own class for the panel?
You can create an anonymous subclass of JPanel with an overriden paintComponent() method. Something like this:
JPanel panel = new JPanel() {
//overriding method here
public void paintComponent(Graphics g) {
g.fillOval(...);
}
};
Related
public void display() {
pan.repaint();
fen.add(pan);
fen.addKeyListener(this);
fen.setResizable(false);
fen.setTitle("Le Jeu 2D");
img.setText("Coucou");
pan.add(img);
pan.repaint();
pan.setBackground(Color.yellow);
fen.setVisible(true);
fen.setSize(480, 272);
pan.repaint();
fen.revalidate();
}
public void paintComponent(Graphics g) {
System.out.println("zzz");
pan.paint(g);
g.setColor(Color.red);
g.drawRect(10, 10, 10, 10);
}
It doesn't draw anything. Why? I have defined the paint component method, so I don't understand why.
Edit: I edited my code, please take a look
You don't create an instance of your Game class and don't add it to the JFrame.
Here is the Game panel which you are painting on:
Game.java
public class Game extends JPanel {
#Override
public final void paintComponent(final Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.drawRect(10, 10, 10, 10);
}
#Override
public Dimension getMinimumSize() {
return new Dimension(300, 300);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
#Override
public Dimension getMaximumSize() {
return new Dimension(300, 300);
}
}
You then need to create an instance of this Game panel and add it to your JFrame:
GameFrame.java
public class GameFrame extends JFrame {
public GameFrame() {
setLocationRelativeTo(null);
setResizable(false);
setTitle("2D Game");
Game game = new Game();
setContentPane(game);
pack();
setVisible(true);
}
}
Then when you create an instance of the JFrame:
Example.java
public class Example {
public static void main(String[] args) {
new GameFrame();
}
}
The panel will be added, and painted:
You never create an instance of the Game class and you never add the Game class to the frame. Even if you did create an instance the size would still be (0, 0) so there would be nothing to paint.
Basically the whole structure of your code is wrong.
I suggest you start over and start with the demo code found in the Swing tutorial on Custom Painting.
The basic structure of your code seems weird.
You could instantiate a JFrame in your main control class, ie. it should be GAME class in this case. Then you can create a new JPanel class and add its object into the JPanel object. Within the JPanel class, you can create all the elements you need and set corresponding parameters. You could also add the event listener in an inner class or a separate class.
I'm new with Java and I'm trying to a class that extends JPanel. I have a updateView() method that is suppose to draw rounded rectangles with text in the middle inside the JPanel. Also, I would need to stock the textfield and the rounded rectangle in a LinkedHashMap. I already got a var for this, I just don't know witch type of var I need to use.
I'have been searching the solution for a while, and all the answers I found are either to complicated for me to understand or just doesn't apply to my case.
I know that it's almost nothing, but here is what I got so far...
package game;
import javax.swing.JPanel;
public class GameNumView extends JPanel
{
private Map<Integer,Integer> backgroundText = new LinkedHashMap<"My rounded rectangle","My textfield">();
public GameNumView()
{
}
public void UpdateView(String[] pNumbers)
{
//Create the background
//Create the text
}
}
I'll give you the right path. It's up to you to adapt it to your existing code.
The idea is to use the Graphics object with the paintComponent method of an extended class of JPanel.
Here is the code, it is clear enough I think but if you have any question, do not hesitate.
The MyFrame class :
public class MyFrame extends JFrame {
public MyFrame(){
this.setTitle("Hello");
this.setSize(200, 200);
this.setLocationRelativeTo(null);
MyPanel pan = new MyPanel();
pan.setBackground(Color.ORANGE);
this.setContentPane(pan);
this.setVisible(true);
}
public static void main(String[] args) {
MyFrame f = new MyFrame();
}
}
And here is the MyPanel class :
public class MyPanel extends JPanel{
#Override
public void paintComponent(Graphics g) {
g.setColor(Color.black);
g.drawRoundRect(10, 10, this.getWidth()-20, this.getHeight()-20, 15, 15);
g.setColor(Color.black);
g.drawString("Hello", 75, 75);
}
}
And here is a picture of what you should have :
Here's an abrevated version of what my code looks like:
public class ColorFactory extends JFrame {
public ColorFactory(){
buildTopPanel();
}
public void buildTopPanel(){
JPanel topPanel = new JPanel();
this.add(topPanel, BorderLayout.NORTH);
}
}
As you can see I have a method that makes a new JPanel object when called. How can I access that particular JPanel object from another class? I have a button listener class that I want to change the color of the JPanel from outside the ColorFactory class. This code is right after the ColorFactory class.
public class ButtonListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
//Change JPanel color here.
}
}
Would it be better just to instantiate JPanel in the ColorFactory constructor and then just access it through there?
For starters, you need to make the JPanel a field in ColorFactory, so references to it don't disappear when you exit buildTopPanel(). Once you've saved a reference to it, then you have a couple of choices. From the design standpoint, the bad choice is to expose it, e.g.:
JPanel getTopPanel(){
return topPanel;
}
The better choice is to have your action listener send a message to ColorFactory that says "respondToButton(Color newColor)", and have ColorFactory decide to change topPanel's color... e.g.:
public void respondToButton(Color newColor){
topPanel.setBackground(newColor);
}
You are facing a design issue; in general, this type of situations require more investigation to understand how to end up with a clean and maintainable design.
However, For the specific problem you are reporting, I would:
Create a constructor of ButtonListener that receives a parameter (i.e. the ColorFactory) which could access the information you need, so that you can initialize a field in ButtonListener itself
Create a method changeColor in the ColorFactory. This method actually applies the color change
In the ButtonListener, invoke changeColor on the field, i.e. the reference to the ColorFactory
You should make the JPanel a field of the class like this:
public class ColorFactory extends JFrame {
JPanel topPanel;
public ColorFactory(){
buildTopPanel();
}
public void buildTopPanel(){
topPanel = new JPanel();
this.add(topPanel, BorderLayout.NORTH);
}
public void changeColor(Color color) {
//color changing code here
}
}
now You can get the JPanel from another class.
All you have to do now, is get the ColorFactory into your Button listener:
public class ButtonListener implements ActionListener{
ColorFactory colorFactory;
public ButtonListener(ColorFactory colorFactory) {
this.colorFactory = colorFactory;
}
public void actionPerformed(ActionEvent e) {
colorFactory.changeColor(/* color here */);
}
}
I'd like to know how you are supposed to override a paint method for each panel in the same class and how to call them separately?
I only know about the repaint() call when you are in a class that extends JPanel (so in only one panel), not when you just make panels.
Thanks in advance.
Typically you create a class that extends JPanel to override the paintComponent method:
public class Test extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// code here
}
public void doStuff() { repaint(); }
}
You might consider creating a nested class like so:
public class Test {
public class MyPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// code here
}
}
JPanel panel = new MyPanel();
panel.repaint();
}
Or you can do this without creating a class that extends JPanel:
JPanel panel1 = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// code here
}
};
panel1.repaint();
I think the normal thing is to extend JPanel for each unique panel you wish to create. In other words, each panel you create is its own class. Then you can overwrite the paint method for each individually.
I cannot get this oval to draw on the JFrame.
static JFrame frame = new JFrame("New Frame");
public static void main(String[] args) {
makeframe();
paint(10,10,30,30);
}
//make frame
public static void makeframe(){
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel emptyLabel = new JLabel("");
emptyLabel.setPreferredSize(new Dimension(375, 300));
frame.getContentPane().add(emptyLabel , BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
// draw oval
public static void paint(int x,int y,int XSIZE,int YSIZE) {
Graphics g = frame.getGraphics();
g.setColor(Color.red);
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
The frame displays but nothing is drawn in it. What am I doing wrong here?
You have created a static method that does not override the paint method. Now others have already pointed out that you need to override paintComponent etc. But for a quick fix you need to do this:
public class MyFrame extends JFrame {
public MyFrame() {
super("My Frame");
// You can set the content pane of the frame to your custom class.
setContentPane(new DrawPane());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 400);
setVisible(true);
}
// Create a component that you can actually draw on.
class DrawPane extends JPanel {
public void paintComponent(Graphics g) {
g.fillRect(20, 20, 100, 200); // Draw on g here e.g.
}
}
public static void main(String args[]){
new MyFrame();
}
}
However, as someone else pointed out...drawing on a JFrame is very tricky. Better to draw on a JPanel.
Several items come to mind:
Never override paint(), do paintComponent() instead
Why are you drawing on a JFrame directly? Why not extends JComponent (or JPanel) and draw on that instead? it provides more flexibility
What's the purpose of that JLabel? If it sits on top of the JFrame and covers the entire thing then your painting will be hidden behind the label.
The painting code shouldn't rely on the x,y values passed in paint() to determine the drawing routine's start point. paint() is used to paint a section of the component. Draw the oval on the canvas where you want it.
Also, you're not seeing the JLabel because the paint() method is responsible for drawing the component itself as well as child components. Overriding paint() is evil =)
You are overriding the wrong paint() method, you should override the method named paintComponent like this:
#Override
public void paintComponent(Graphics g)
You need to Override an exist paint method that actually up to dates your Frame. In your case you just created your custom new method that is not called by Frame default.
So change your method to this:
public void paint(Graphics g){
}