Failing to call a call paintcomponent method :( - java

What I am trying to achieve is that the program would draw a line in the middle of the frame as soon as the user has clicked draw. But sadly nothing is happening other than "frame 3" is disappearing. Any ideas about how I could fix the problem?
Here is the method:
Windowj is my frame. Frame3 is the previous frame please don't worry about it.
public static void graf() {
frame3.setVisible(false);
windowj.setSize(400, 500);
windowj.setLocationRelativeTo(null);
windowj.setResizable(false);
windowj.setLayout(null);
windowj.setVisible(true);
windowj.setTitle("Graphs");
windowj.setDefaultCloseOperation(EXIT_ON_CLOSE);
xinwindow.setBounds(30,40, 90, 40);
yinwindow.setBounds(100,100,90,40);
thefunction.setBounds(200,300,90,40);
draw.setBounds(300,200,90,40 );
windowj.add(xinwindow);
windowj.add(yinwindow);
windowj.add(thefunction);
windowj.add(draw);
c.setPreferredSize(new Dimension(300,200));
draw.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
windowj.add(c);
c.revalidate();
c.repaint();
}
And here is the paintcomponent method:
private static Component c = new JComponent() {
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.black);
g.drawLine(50, 0, 70 , 100);
}
};
Any help would be appreciated, and please try to keep it simple, I am a beginner. :)

I will assume you use windowj as your JFrame and that what will happen when you click draw button your use windowj.setVisible(false) and that will make your window disappear
so remove it
2nd thing is you need to put your Component in windowj as windowj.add(c); in your draw ActionListener at actionPerformed before c.revalidate();
and here a little code that I wrote to understand what I mean:
public class DrawLine {
private JFrame windowj = new JFrame();
private JButton draw = new JButton();
private static int width = 640, height = 480;
private static JComponent c = new JComponent() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.black);
g.drawLine((width/2) - 1, 0, (width/2) +1 , height);
}
};
public DrawLine() {
windowj.setDefaultCloseOperation(windowj.EXIT_ON_CLOSE);
windowj.setSize(width, height);
windowj.setLayout(new FlowLayout());
windowj.setResizable(false);
windowj.setLocationRelativeTo(null);
windowj.setVisible(true);
draw = new JButton("Draw");
draw.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//i don't know why you set windowj(windowj) false but that will close your window
//windowj.setVisible(false);
//add component to windowj(windowj)
windowj.add(c);
c.revalidate();
c.repaint();
}
});
c.setPreferredSize(new Dimension(width, height-100));
windowj.add(draw);
}
public static void main(String[] args) {
new DrawLine();
}
}

Here is the modified code:
private JFrame frame3, windowj;
private JPanel xinwindow, yinwindow,thefunction;
private JButton draw;
private static Component c = new JComponent() {
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.black);
g.drawLine(50, 0, 70 , 100);
}
};
public DrawLine() {
xinwindow = new JPanel();
yinwindow = new JPanel();
thefunction = new JPanel();
draw = new JButton("Draw");
//i ignored frame3 as you said so just ignore my implementation here
frame3 = new JFrame();
frame3.setVisible(false);
windowj = new JFrame();
windowj.setSize(400, 500);
windowj.setLocationRelativeTo(null);
windowj.setResizable(false);
windowj.setLayout(null);
windowj.setVisible(true);
windowj.setTitle("Graphs");
windowj.setDefaultCloseOperation(EXIT_ON_CLOSE);
/*i used setBackground(Color.anycolor); to make it easier for me to know where
your window is in your frame*/
xinwindow.setBackground(Color.RED);
xinwindow.setBounds(30,40, 90, 40);
yinwindow.setBackground(Color.yellow);
yinwindow.setBounds(100,100,90,40);
thefunction.setBounds(200,300,90,40);
thefunction.setBackground(Color.green);
draw.setBounds(300,200,90,40 );
windowj.add(xinwindow);
windowj.add(yinwindow);
windowj.add(thefunction);
windowj.add(draw);
//here use setBonds instead of setPreferredSize
c.setBounds(100, 200, 200, 200);
draw.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
windowj.add(c);
c.revalidate();
c.repaint();
}
});
}
public static void main(String[] args) {
new DrawLine();
}
hope that solve your problem.

Related

What is the problem when KeyListener is added yet keyEvent is not working when pressed?

My Listener is added to the JFrame/JPanel. The problem is that when I pressed a button, nothing is happening. What might be the problem here?
The following are the codes used:
public class GAMEGAMEHA extends JPanel{
public static JFrame PacmanMainFrame = new JFrame();
TheJGame newGame;
GAMEGAMEHA() {
setSize(new Dimension(1200, 700));
JLabel BG = new JLabel();
JButton start = new JButton();
JButton howTo = new JButton();
JButton credit = new JButton();
JButton exit = new JButton();
setLayout(null);
start.setIcon(new ImageIcon(getClass().getResource("/data/SB.png")));
start.setContentAreaFilled(false);
start.addActionListener((ActionEvent e) -> {
newGame = new TheJGame();
GAMEGAMEHA.PacmanMainFrame.getContentPane().removeAll();
System.out.println("Removed Components");
GAMEGAMEHA.PacmanMainFrame.add(newGame);
System.out.println("Added Game");
GAMEGAMEHA.PacmanMainFrame.addKeyListener(newGame);
System.out.println("Added KeyListeners");
GAMEGAMEHA.PacmanMainFrame.setVisible(true);
System.out.println("Set Visiblity to True");
});
start.setBorderPainted(false);
add(start);
start.setBounds(440, 140, 300, 70);
howTo.setIcon(new ImageIcon(getClass().getResource("/data/HowToButton.jpg")));
howTo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e
) {
HowTo HowToScreen = new HowTo();
GAMEGAMEHA.PacmanMainFrame.getContentPane().removeAll();
GAMEGAMEHA.PacmanMainFrame.add(HowToScreen);
GAMEGAMEHA.PacmanMainFrame.setVisible(true);
}
});
howTo.setBorderPainted(false);
add(howTo);
howTo.setBounds(440, 220, 300, 70);
credit.setIcon(new ImageIcon(getClass().getResource("/data/CreditsButton.jpg")));
credit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e
) {
Credit CreditScreen = new Credit();
GAMEGAMEHA.PacmanMainFrame.getContentPane().removeAll();
GAMEGAMEHA.PacmanMainFrame.add(CreditScreen);
GAMEGAMEHA.PacmanMainFrame.setVisible(true);
}
});
credit.setBorderPainted(false);
add(credit);
credit.setBounds(440, 300, 300, 70);
exit.setIcon(new ImageIcon(getClass().getResource("/data/ExitButton.jpg")));
exit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e
) {
System.exit(JFrame.EXIT_ON_CLOSE);
}
}
);
exit.setBorderPainted(
false);
add(exit);
exit.setBounds(
440, 380, 300, 70);
BG.setIcon(
new ImageIcon(getClass().getResource("/data/MainMenu.jpg")));
BG.setText(
"BackgroundImage");
add(BG);
BG.setBounds(
0, 0, 1200, 700);
}
public static void main(String[] args) {
GAMEGAMEHA GameMENU = new GAMEGAMEHA();
PacmanMainFrame.setSize(new Dimension(1200, 700));
PacmanMainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
PacmanMainFrame.setTitle("THE JUNGLE GAME: A Object-Oriented Programming Project");
PacmanMainFrame.setResizable(false);
PacmanMainFrame.setLocationRelativeTo(null);
PacmanMainFrame.add(GameMENU);
PacmanMainFrame.setVisible(true);
}
}
This is game started:
The problem is here. The Main menu is good but when going here, it doesn't accept nor read any key.
public class TheJGame extends JPanel implements KeyListener {
BackgroundGame BG = new BackgroundGame();
MainCharacter bens = new MainCharacter();
static int MainCx = 22;
static int MainCy = 20;
static int BGx = 0;
static int BGy = 545;
TheJGame() {
bens.initializeMChar();
BG.initializeGGround();
setBounds(0, 0, 1200, 700);
setFocusable(true);
}
#Override
public void paint(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, 1200, 700);
g.drawImage(BG.GGround, BGx, BGy, this);
g.drawImage(BG.GGround, BGx + 1200, BGy, this);
g.drawImage(bens.MCharacter, MainCx, MainCy, this);
updateBG();
updateFall();
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_SPACE) {
MainCy+=5;
repaint();
}
}
#Override
public void keyReleased(KeyEvent e) {
}
public void updateFall() {
if (MainCy <= 445) {
MainCy += 1;
repaint();
}
}
private void updateBG() {
BGx -= 1;
if (BGx == -1200) {
BGx = 0;
}
repaint();
}
}
Main Problem
The "major" problem is, KeyListener is a poor choice for monitoring keyboard input in Swing, it suffers from a focus issue, where the component it is registered to must be focusable AND have keyboard focus and since you're adding buttons to the UI, they will steal focus from the component.
A better, overall solution, is to use the Key Bindings API which gives you the control to determine at what level of focus the bindings should be triggered
Additional problems...
null layouts are notoriously difficult to manage and maintain. There are a lot of factors which go into determining how best a component should appear on the screen. You should avoid null layouts where possible and make use of one or more layout managers, they will save a lot of your hair
You've overriding paint, but you've failed to honour the paint chain (by not calling super.paint). Painting is a complex process, made up of a number of steps.
As a general rule, you should override paintComponent (and call super.paintComponent before doing any custom painting).
Have a read through Painting in AWT and Swing and Performing Custom Painting for more details about painting in Swing
You did not add the key listener to the JPnael simply implementing the interface is not enough you have to add it to the panel.
addKeyListner(this);
Add this line of code to your constructor.

How do i get my action listener to remove the contents from the current JPanel?

I am trying to add a button which will when pressed, clear the contents off the JPanel and return the panel back to its original set-up. How would i go about doing this? I have tried to revalidate, removeall etc but none have worked for me so far. Any suggestions on how i can do this? I will attach the code below, Help would be greatly appreciated.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class WindowBlind extends JFrame
implements ChangeListener, ActionListener {
private JSlider slider;
private int sliderValue = 0;
private JPanel panel;
private JButton open;
private JButton close;
private JButton exit;
private boolean clear;
public static void main(String[] args) {
WindowBlind applic = new WindowBlind();
applic.setLocation(100,100);
applic.setVisible(true);
} // main
public WindowBlind() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("WindowBlind");
setSize(300,300);
Container window = getContentPane();
window.setLayout(new FlowLayout());
panel = new JPanel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
paintScreen(g);
} // paintComponent
};
panel.setPreferredSize(new Dimension(200, 200));
panel.setBackground(Color.white);
window.add(panel);
slider = new JSlider(JSlider.VERTICAL,0,100,0);
slider.setInverted(true); // 0 will be at top, not bottom, of vertical slider
window.add(slider);
slider.addChangeListener(this); // Register for slider events
JButton open = new JButton("Open Slider");
window.add(open);
open.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
JButton close = new JButton("Close Slider");
window.add(close);
close.addActionListener(this);
JButton exit = new JButton("Exit Slider");
window.add(exit);
exit.addActionListener(this);
} // WindowBlind constructor
public void paintScreen(Graphics g) {
g.setColor(Color.cyan);
g.fillRect(70, 40, 60, 100); // The blue sky
g.setColor(Color.lightGray);
g.fillRect(70, 40, 60, sliderValue); // The blind, partially closed
g.setColor(Color.black);
g.drawRect(70, 40, 60, 100); // The window frame
} // paintScreen
// When the slider is adjusted, this method is called automatically
public void stateChanged(ChangeEvent e) {
sliderValue = slider.getValue(); // Fetch the slider's current setting
repaint(); // Force a screen refresh (paintComponent is called indirectly)
} // stateChanged
#Override
public void actionPerformed(ActionEvent e) {
}
}
I'm taking a HUGE guess and assuming you want to reset the slider to it's "default" state, which would suggest that you need to change the sliderValue, something like...
close.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sliderValue = 0;
slider.repaint();
}
});
A better solution would be to generate a self contained class which encapsulated all this functionality, for example...
public class SliderPane extends JPanel {
private double sliderValue;
public double getSliderValue() {
return sliderValue;
}
public void setSliderValue(double sliderValue) {
this.sliderValue = Math.max(Math.min(1.0, sliderValue), 0);
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
g.setColor(Color.cyan);
g.fillRect(0, 0, width, height); // The blue sky
g.setColor(Color.lightGray);
g.fillRect(0, 0, width, (int)(sliderValue * height)); // The blind, partially closed
g.setColor(Color.black);
g.drawRect(0, 0, width, height); // The window frame
}
}
Then you could control the slider value through the setSliderValue method.
This also allows you to specify the slider value as percentage, meaning that the size of the component doesn't matter as the area filled is a percentage of the height
This is because you always call paintScreen from the panel's paintComponent method. I would suggest this midification:
panel = new JPanel() {
boolean drawMe = true;
public void paintComponent(Graphics g) {
super.paintComponent(g);
if(drawMe)
paintScreen(g);
} // paintComponent
};
Whenever you want to clear the panel, do this:
panel.drawMe=false;
panel.invalidate();

repaint() is not working

I want to draw circle and align it to center, but when I am calling repaint() nothing happens. I tried almost everything, I have changed layouts, alignments, but always the same. This is my code:
public class Frame extends JFrame {
JButton button,dugme;
JLabel lab;
public Frame(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(480,320);
setResizable(false);
setLocationRelativeTo(null);
setLayout(new FlowLayout());
setVisible(true);
button = new JButton("Klikni me");
button.setSize(75,75);
add(button);
button.setHorizontalAlignment(SwingConstants.RIGHT);
dugme= new JButton("Klikni opet");
dugme.setSize(75,75);
add(dugme);
dugme.setHorizontalAlignment(SwingConstants.LEFT);
lab = new JLabel("Ovde je tekst koji se menja");
add(lab);
lab.setHorizontalAlignment(SwingConstants.CENTER);
Handler handler = new Handler();
Handler1 handler1= new Handler1();
repaint();
button.addActionListener(handler);
dugme.addActionListener(handler1);
}
public void paintComponent(Graphics g){
super.paintComponents(g);
g.fillOval(30, 30, 60, 75);
}
public class Handler implements ActionListener{
public void actionPerformed(ActionEvent e){
repaint();
lab.setText("New text");
}
}
public class Handler1 implements ActionListener{
public void actionPerformed(ActionEvent e){
lab.setText("Same text again ");
repaint();
}
}
}
public void paintComponent(Graphics g){
super.paintComponents(g);
Breaks the paint chain, it should be:
public void paintComponent(Graphics g){
super.paintComponent(g); // no S in method name..

How can I move my JButton to the right side of my JPanel?

For a programming class, I was asked to create a replica of an iCalendar app. I'm using JAVA to code it, and JFrame and JPanel to draw it. Here is a SSCCEE of my problem:
import java.awt.*;
import javax.swing.*;
public class Mainie extends JFrame {
private JButton back = new TriangleButton(true),
front = new TriangleButton(false);
public Mainie(){
super();
setSize(800, 400);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel months = new JPanel();
final JPanel days = new JPanel();
JLabel one = new JLabel("Hallo");
one.setHorizontalAlignment(JLabel.CENTER);
back.setHorizontalAlignment(SwingConstants.LEFT);
front.setHorizontalAlignment(SwingConstants.RIGHT);
months.setLayout(new BorderLayout());
months.add(back, BorderLayout.WEST);
months.add(one, BorderLayout.CENTER);
months.add(front, BorderLayout.EAST);
days.setLayout(new GridLayout(1,1));
days.add(new JButton("Meister Camickr"));
months.setAlignmentX(CENTER_ALIGNMENT);
add(months, BorderLayout.NORTH);
add(days, BorderLayout.CENTER);
setVisible(true);
}
public static void main(String[] args){
new Mainie();
}
}
class TriangleButton extends JButton {
private Shape triangle = createTriangle();
public void paintBorder(Graphics g) {
((Graphics2D) g).draw(triangle);
}
public void paintComponent(Graphics g) {
((Graphics2D) g).fill(triangle);
}
public Dimension getPreferredSize() {
return new Dimension(200, 100);
}
public boolean contains(int x, int y) {
return triangle.contains(x, y);
}
public TriangleButton(boolean pointLeft) {
super();
if (!pointLeft)
this.triangle = createRTriangle();
}
private Shape createTriangle() {
Polygon p = new Polygon();
p.addPoint(0, 20);
p.addPoint(20, 0);
p.addPoint(20, 40);
return p;
}
private Shape createRTriangle() {
Polygon p = new Polygon();
p.addPoint(20, 20);
p.addPoint(0, 0);
p.addPoint(0, 40);
return p;
}
}
If you compile this, you can see that my JButton is too far to the left. How can I move it to the right?
The basic problem with those buttons is that the button is very wide and the visual indicator is to the left. Put a border around them and it becomes obvious.
OTOH I would use an entirely different approach, using text for the buttons and a factory method to make them look as expected.
import java.awt.*;
import javax.swing.*;
public class CustomPointerButtons {
JPanel ui;
CustomPointerButtons() {
initUI();
}
private final void initUI() {
ui = new JPanel(new BorderLayout(4, 4));
JPanel topPanel = new JPanel(new BorderLayout(4, 4));
ui.add(topPanel, BorderLayout.PAGE_START);
ui.add(new JButton("Mister Mix")); //will default to CENTER
topPanel.add(new JLabel("Blah, Blah.."));
JButton back = getMinimalButton(new String(Character.toChars(9668)));
topPanel.add(back, BorderLayout.LINE_START);
JButton forward = getMinimalButton(new String(Character.toChars(9658)));
topPanel.add(forward, BorderLayout.LINE_END);
}
public JButton getMinimalButton(String text) {
JButton b = new JButton(text);
b.setFont(b.getFont().deriveFont(40f));
b.setMargin(new Insets(0,0,0,0));
b.setContentAreaFilled(false);
b.setBorder(null);
return b;
}
public final JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
JFrame f = new JFrame("Custom Pointer Buttons");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setContentPane(new CustomPointerButtons().getUI());
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
The problem is your random preferred size doesn't represent the real size of the triangle.
You can do something like:
public Dimension getPreferredSize() {
//return new Dimension(200, 100);
Rectangle bounds = triangle.getBounds();
return new Dimension(bounds.width, bounds.height);
}
You still have other problems because you will still have painting artifacts. You should always invoke super.paintComponent() when you override the method:
public void paintComponent(Graphics g) {
super.paintComponent(g);
((Graphics2D) g).fill(triangle);
}
However, this still doesn't really work because the button does other painting as well. So the real problem is that you should not be trying to do custom painting of the button. What you really want to do is custom painting of an Icon. Then you can just add the Icon to the button.
You may want to check out Playing With Shapes. You can use the ShapeIcon class to create your icons. This will provide a more flexible solution since I'm guess all shapes are not represented by an ascii character.

Call paint method from game loop at the start of a button

Hi I'm trying to call the paint method every time in a game loop.At the moment the screen pops up with a label and a button once the button has been pressed the label and button go which i want but i can't get the paint method to start i tried j.repaint() & j.validate() neither accessed paint method.Any help would be appreciated.
package sgame;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class SGame extends JPanel
{
public static void main(String[] args)
{
final JFrame window = new JFrame("hello");
final JPanel window1 = new JPanel();
Timer loop = new Timer(1000, new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
GameLoop(window1);
}
});
Window(window, loop);
}
public static void Window(final JFrame window, final Timer loop)
{
final JButton b1 = new JButton("GO!");
b1.setLocation(210, 300);
b1.setSize(70, 50);
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(500, 500);
window.setLocation(420, 170);
window.setBackground(Color.BLACK);
final JLabel Title = new JLabel("Snake", JLabel.CENTER);
Title.setFont(new Font("Times New Roman", Font.ITALIC, 60));
Title.setVerticalAlignment(JLabel.CENTER);
Title.setForeground(Color.WHITE);
window.add(b1);
window.add(Title);
b1.addActionListener(new ActionListener() // runs when buttons pressed
{
#Override
public void actionPerformed(ActionEvent e) // clears header,button and starts timer
{
b1.invalidate();
b1.setVisible(false);
Title.setVisible(false);
Title.invalidate();
loop.start();
}
});
}
public static void GameLoop(JPanel j)
{
// Call paint method
}
public void paintComponent(Graphics g)
{
g.setColor(Color.yellow);
g.drawRect(30, 30, 30, 30);
}
}
The paintComponent() method in SGame is never called because you didn't instanciate any SGame object. And window1 has not been added to the frame.
Something like this should be better :
public class SGame extends JPanel {
private Timer loop;
public SGame(){
loop = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
gameLoop();
}
});
}
public static void main(String[] args) {
final JFrame window = new JFrame("hello");
final JButton b1 = new JButton("GO!");
b1.setLocation(210, 300);
b1.setSize(70, 50);
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(500, 500);
window.setLocation(420, 170);
window.setBackground(Color.BLACK);
final JLabel Title = new JLabel("Snake", JLabel.CENTER);
Title.setFont(new Font("Times New Roman", Font.ITALIC, 60));
Title.setVerticalAlignment(JLabel.CENTER);
Title.setForeground(Color.WHITE);
window.add(b1);
window.add(Title);
b1.addActionListener(new ActionListener() { // runs when buttons pressed
#Override
public void actionPerformed(ActionEvent e) // clears header,button
{
b1.invalidate();
b1.setVisible(false);
Title.setVisible(false);
Title.invalidate();
SGame sg = new SGame();
window.add(sg);
sg.start();
}
});;
}
public void start(){
loop.start();
}
public void gameLoop() {
repaint();
}
#Override
public void paintComponent(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.yellow);
g.drawRect(30, 30, 30, 30);
}
}

Categories