Where to place JOptionPaneShowInputDialog code?
Where to place JOptionPaneShowInputDialog code?Where to place JOptionPaneShowInputDialog code?
Where to place JOptionPaneShowInputDialog code?
Where to place JOptionPaneShowInputDialog code?
I would like to add a JoptionPaneShowInputDialog()(not in code yet) inside the code herebelow.
I can do, but I cannot make the dialog appearing in the black panel,before the recursion.
The dialog appears after the drawing...
public class FractalTree extends JPanel implements ActionListener
{
int x1=350;
int y1=600;
int angle=-90;
int depth=11;
int k=10;
JLabel label_1;
private void drawTree(Graphics g, int x1, int y1, double angle, int depth, int k)
{
if(depth==11)
g.setColor(Color.GRAY);
g.fillRect(100, 600, 1160, 10);
g.setColor(Color.white);
if (depth == 0) return;
((Graphics2D) g).setStroke(new BasicStroke((float) (k*0.9)));
int x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 11*Math.random()+1);
int y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 11*Math.random()+1);
if(depth<3)
{
g.setColor(Color.green);
}
g.drawLine(x1, y1, x2, y2);
drawTree(g, x2, y2, angle - 19, depth-1,k-1);
drawTree(g, x2, y2, angle + 19, depth-1,k-1);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.white);
drawTree(g,x1,y1,angle,depth,k);
drawTree(g,x1+600,y1,angle,depth,k);
}
public FractalTree()
{
this.setBackground(Color.black);
}
public static void gui()
{
JFrame f=new JFrame("fractal tree");
JLabel label_1=new JLabel("<html>RANDOM TREE<br><center>FRACTAL");
label_1.setForeground(Color.red);
Font font = new Font("Courier", Font.BOLD,25);
label_1.setFont(font);
FractalTree ft=new FractalTree();
f.getContentPane().add(ft);
f.setSize(1500, 1000);
JButton button = new JButton("Close Me");
button.addActionListener(ft);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ft.add(label_1);
ft.add(button);
f.setUndecorated(true);
f.setVisible(true);
}
public static void main(String[] args)
{
gui();
}
#Override
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
}
May I ask some help?
Thanks
The question and intent are some what unclear. What is the purpose of the dialog?
I assume you want to gather some information which can then be passed to the FractalTree to change it's rendering
The question and intent are some what unclear. What is the purpose of the dialog?
I assume you want to gather some information which can then be passed to the FractalTree to change it's rendering, in that case you probably need to put the dialog before the creation of the FractalTree
public static void gui()
{
// You can put the dialog here...
JFrame f=new JFrame("fractal tree");
//...
If you want to change the properties FractalTree after its been displayed, then you probably need to use a JButton and a ActionListener and place the dialog in there ... or provide a second view to gather the properties directly
In fact, the purpose of the dialog box is to ask the recursion level. If I place it like you propose, its ok, but the dialog box appears alone, not in the black panel, and I would like that it appears in the panel...
Let's just be clear, SO is NOT a tutorial or mentoring site. Your problem isn't a technical problem, but an experience one. You should spend more time reading through tutorials like Creating a GUI With Swing and trying things. This is how you will become a better developer and learn to solve your own problems.
Based on your feedback, JOptionPane isn't what you need.
Instead, you need to take a slightly different approach and supply your own input component.
First, you need to change FractalTree so that you can modify the depth property more easily (and set the initial depth to 0 so it will stop drawing)
public class FractalTree extends JPanel implements ActionListener {
private int depth = 0; // set to 0 to stop it from rendering
public void setDepth(int depth) {
this.depth = depth;
repaint();
}
public int getDepth() {
return depth;
}
Next, you need to create your own input component, which can take input from the user and update the tree
public class InputPane extends JPanel {
private FractalTree fractalTree;
private JTextField depthField;
public InputPane(FractalTree fractalTree) {
this.fractalTree = fractalTree;
depthField = new JTextField(10);
depthField.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
String text = depthField.getText().trim();
try {
int value = Integer.parseInt(text);
fractalTree.setDepth(value);
} catch (NumberFormatException exp) {
JOptionPane.showMessageDialog(InputPane.this, text + " is not a valid numerical value");
}
}
});
}
}
Then you want to create a new entry point that can combine the two...
import java.awt.EventQueue;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
FractalTree tree = new FractalTree();
InputPane input = new InputPane(tree);
JFrame frame = new JFrame();
frame.add(tree);
frame.add(input, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Yes, this is going to produce a small window, because FractalTree doesn't define any sizing hints, which can be solved by overriding it's getPreferredSize method and returning a more suitable size.
This is going to put you own a "better path", there are still issues you're going to have to solve, because doing it all for you won't help you
Related
I'm having trouble with my jbutton not displaying. If i do not use paintComponent, then my JButtons with images show up no problem. However now, the image does not show up. If i hover over where it should be, the image shows up for one second. So it's like the button is still there, just maybe below the background?
public class Game extends JPanel implements KeyListener, ActionListener {
//layout variables
private ImageIcon right,left,up,down;
private JButton rightButton,leftButton,upButton,downButton;
//play variables
private boolean play=false;
private int score=0;
private int paddleX= 200; //paddle X position
private int paddleY= 300; //paddle Y pos
private int ballX= 210; //ball x position
private int ballY= 260; //ball y position
private int ballXdir=-1; //x direction
private int ballYdir=-2; //y direction
private Timer time; //my timer
public Game() {
Display(); //display the layout
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
time= new Timer(8,this);
time.start();
}
public void Display(){
//setLayout
this.setLayout(null);
//Setting the Images
//right = new ImageIcon(getClass().getResource("images\\rightIcon.png"));
left = new ImageIcon(getClass().getResource("images\\leftIcon.png"));
up = new ImageIcon(getClass().getResource("images\\upIcon.png"));
down = new ImageIcon(getClass().getResource("images\\downIcon.png"));
//Setting the JButtons for the arrow images
rightButton= new JButton("right");
rightButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(paddleX>=400){
paddleX=400;
}
else{
moveRight();
}
repaint();
}
});
//rightButton.setOpaque(false);
//rightButton.setContentAreaFilled(false);
//rightButton.setBorderPainted(false);
leftButton= new JButton(left);
leftButton.setOpaque(false);
leftButton.setContentAreaFilled(false);
leftButton.setBorderPainted(false);
upButton= new JButton(up);
upButton.setOpaque(false);
upButton.setContentAreaFilled(false);
upButton.setBorderPainted(false);
downButton= new JButton(down);
downButton.setOpaque(false);
downButton.setContentAreaFilled(false);
downButton.setBorderPainted(false);
//setting image bounds and adding it to screen
rightButton.setBounds(135,450,50,50);
leftButton.setBounds(45,450,50,50);
upButton.setBounds(90,400,50,50);
downButton.setBounds(90,500,50,50);
//rightButton.addActionListener(this);
leftButton.addActionListener(this);
add(upButton);
add(downButton);
add(leftButton);
add(rightButton);
}
//painting the screen with graphics
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(25,25,425,300); //game area
//drawing the paddle
g.setColor(Color.YELLOW);
g.fillRect(paddleX,paddleY,50,8);
//drawing the ball
g.setColor(Color.PINK);
g.fillOval(ballX,ballY,20,20);
g.dispose();
}
#Override
public void actionPerformed(ActionEvent e) {
time.start();
if(e.getSource()==right) {
if(paddleX>=400){
paddleX=400;
}
else{
moveRight();
}
}
if(e.getSource()==left) {
if(paddleX<35){
paddleX=35;
}
else{
moveLeft();
}
}
repaint();
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_RIGHT){
if(paddleX>=400){
paddleX=400;
}
else{
moveRight();
}
}
if(e.getKeyCode()==KeyEvent.VK_LEFT){
if(paddleX<35){
paddleX=35;
}
else{
moveLeft();
}
}
}
#Override
public void keyReleased(KeyEvent arg0) {
}
#Override
public void keyTyped(KeyEvent arg0) {
}
public void moveRight(){
play=true;
paddleX+=10;
}
public void moveLeft(){
play=true;
paddleX-=10;
}
}
I highly recommend having a look at Performing Custom Painting and Painting in AWT and Swing as it will explain how the painting system works.
Basically, you are passed a reference to the Graphics context which is currently been used to perform the current paint pass, via the paintComponent method. This is a shared resource. All components involved in the paint pass are passed the same Graphics context.
By calling dispose, you are releasing all the underlying resources for the context, which can, on some systems, prevent other components from been painted.
But they paint when I move my mouse over them
Because components can be painted independently of their parent, but you also call repaint on the parent component, which will, you guessed it, paint it's children.
Recommendations
Create a custom component dedicated solely to performing the custom painting operations (and possible some of the other basic game functions)
Create another component to hold the buttons (and make use of appropriate layouts)
Use a some kind of data model which is shared between them. This model will hold the state of the "actions" (ie up/down/left/right) and the "engine" will use this information to update the state of the game.
Make use of the Key bindings API which will solve the unreliability issues associated with KeyListener
I created this java program and I wanted an output of which if int x and int y are above 100, it would draw a rectangle. But it doesn't. How can I make it work?Is there another line of code I need to add?
Here's my code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class GameSetup extends JPanel implements MouseMotionListener{
public static JFrame njf = new JFrame("Test");
public static int x, y;
public static void main(String[] args){
GameSetup gs = new GameSetup();
njf.add(gs);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
this.setBackground(Color.BLACK);
g.setColor(Color.GREEN);
g.fillRect(150, 75, 200, 100);
g.setColor(Color.ORANGE);
g.drawString("Play", 239, 123);
njf.addMouseListener(new MouseAdapter() {
public void mouseMoved(MouseEvent e) {
x = e.getX();
y = e.getY();
}
});
if(x > 100 && y > 100){
g.drawRect(10, 10, 100, 100);
}
}
public GameSetup(){
njf.setSize(500,500);
njf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
njf.setResizable(false);
njf.setLocationRelativeTo(null);
njf.setVisible(true);
}
#Override
public void mouseDragged(MouseEvent arg0) {
}
#Override
public void mouseMoved(MouseEvent e) {
}
}
Okay, there are several things wrong with the code that you included above.
The first that stood out to me was the way that you are adding the mouse action listener to frame. There are multiple things that are wrong with this.
First of all, you are doing this in the paintComponent method, which, if it works, is still considered to be bad practice because the paintComponent method may be called multiple times. Do that, as pointed out by the comments, in the constructor of the panel.
The second is that you are adding the mouse listener to the frame, not the panel, which doesn't work because the panel is "above" the frame, so the mouse event will only be recognized within the panel. Your best bet here is to add a MouseMotionListener directly to the panel itself.
The third is that you are implementing the MouseMotionListenerinterface in the GameSetup class, but never actually doing anything with this implementation. So what I did was that I got rid of the inner class, and just had the panel be its own MouseMotionListnener
The second thing that is wrong with the code is that the paintComponent method is only called at certain points in time (see this). That means that even though the mouse might have moved within the zone, your paintComponent method isn't being called to update the screen accordingly. For this, you need to call the repaint method for your panel.
The third is that you didn't set a size for your panel, and the default one is 0x0, so you need to set a size of your panel (which should be the same as the frame itself) (if you want to keep the default layout).
All of that being said, here is your code that I fixed up. I added a variable called enteredZone to keep track of if the mouse had previously entered the zone, so that the rectangle would stay up even if the mouse left the zone after entering it (its your choice if you want to keep it). Note that there are other things with this code that might be considered bad practice, but this is enough to get you started:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class GameSetup extends JPanel implements MouseMotionListener {
public static JFrame njf = new JFrame("Test");
public static int x = 0, y = 0;
public static boolean enteredZone = false;
public static void main(String[] args) {
GameSetup gs = new GameSetup();
gs.addMouseMotionListener(gs);
njf.add(gs);
njf.setVisible(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.BLACK);
g.setColor(Color.GREEN);
g.fillRect(150, 75, 200, 100);
g.setColor(Color.ORANGE);
g.drawString("Play", 239, 123);
if (x > 100 && y > 100 || enteredZone){
g.drawRect(10, 10, 100, 100);
enteredZone = true;
}
}
public GameSetup() {
super();
setSize(500, 500);
njf.setSize(500,500);
njf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
njf.setResizable(false);
njf.setLocationRelativeTo(null);
}
#Override
public void mouseDragged(MouseEvent arg0) {
}
#Override
public void mouseMoved(MouseEvent e) {
x = e.getX();
y = e.getY();
if (x > 100 && y > 100) repaint();
}
}
I want to develop a Java Applet which shows visualization of Sorting. So I have written code like this...
public class SortNumbersGUI extends JApplet {
private static final long serialVersionUID = 1L;
List<Integer> randomList;
JLabel numberLabel;
JButton sortButton;
#Override
public void init() {
randomList = MyRandom.myRandom();
setSize(400, 400);
setLayout(new FlowLayout());
sortButton = new JButton("Sort");
sortButton.setBounds(50, 0, 50, 10);
sortButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Collections.sort(randomList);
removeAll();
repaint();
}
});
this.add(sortButton);
super.init();
}
#Override
public void paint(Graphics g) {
int y = 20;
for (Integer i : randomList) {
g.drawString(i.toString(), 0, y + 10);
g.fillRect(20, y, (i * 10) / 10, 5);
y = y + 20;
}
}
}
But, I am facing two problems here..
Sort button, which is JButton is not always visible. When i am placing mouse cursor over that sort button place then only it is appearing.
The results are overriding when I am calling repaint() method. As the bellow image
Result Image (As I don't have reputation I am pasting the image link.)
Please help me to solve this problem.
Thank you in Advance.
#Override
public void paint(Graphics g) {
// ..
Should be:
#Override
public void paint(Graphics g) {
super.paint(g); // paints **BG**, border etc.
// ..
Your problem is that you are overridding paint instead of paintComponent, and also you are not calling super.paint/Component (also a good practice, though possibly not 100% necessary here).
Because of how you've overridden paint(), you button is not getting automatically painted when the JApplet is painted
I want to be able to click the JButton and change the next individual ellipse I make to its respective color, Red or Black, from its default Blue. So far I'm able to change the color of all the ellipses I have made.
public class MainClient {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainClient window = new MainClient();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public MainClient() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final SpriteField panel = new SpriteField();
panel.setBounds(0, 110, 782, 331);
panel.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
int tX = e.getX();
int tY = e.getY();
panel.CreateObjectAt(tX,tY);
}
});
frame.getContentPane().setLayout(null);
panel.setBackground(Color.LIGHT_GRAY);
frame.getContentPane().add(panel);
final JButton btnRed = new JButton("black");
btnRed.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
panel.setColor(Color.BLACK);
}
});
btnRed.setBounds(229, 500, 97, 25);
frame.getContentPane().add(btnRed);
JButton btnRed_1 = new JButton("red");
btnRed_1.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
panel.setColor(Color.RED);
}
});
btnRed_1.setBounds(342, 500, 97, 25);
frame.getContentPane().add(btnRed_1);
}
}
I have a SriteField Class
public class SpriteField extends JPanel
{
ArrayList<RoundSprite>mSprites = new ArrayList<RoundSprite>();
private Color color = Color.BLUE;
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
AffineTransform tOldTransform = g2.getTransform();
for(RoundSprite tOne:mSprites)
{
tOne.DrawSprite(g2, color);
}
g2.setTransform(tOldTransform);
}
public void CreateObjectAt(int tX, int tY)
{
//make sprite
RoundSprite mLonely = new RoundSprite();
//set position
mLonely.SetPosition(tX, tY);
//add to array
mSprites.add(mLonely);
repaint();
}
public void setColor(Color color)
{
this.color = color;
repaint();
}
}
I have a RoundSprite Class
public class RoundSprite
{
int mX;
int mY;
private Color color;
void DrawSprite(Graphics2D g2, Color color)
{
AffineTransform tOldTransform = g2.getTransform();
g2.setColor(color);
g2.translate(mX, mY); //got it out from the corner
g2.draw(new Ellipse2D.Double(-15, -22, 30, 50));
g2.setTransform(tOldTransform);
}
public void SetPosition(int tX, int tY) //g2.translate
{
mX = tX;
mY = tY;
}
There are three core issues...
One
In order for the panel_1 MouseListener to change the color of the sprites within panel, the MouseListener requires a reference to the panel.
You could declare the panel as final within the initialize method, but I prefer to make the panel a private instance field of the MainClient.
Two
In order to change the color, the SpriteField needs to provide a means by which interested parties can request a change.
This is going to require SpriteField to provide some kind of method that interested parties can call when they need to, for example, a setColor method...
public class SpriteField extends JPanel {
private Color color = Color.BLACK;
//...
public void setColor(Color color) {
this.color = color;
repaint();
}
Then panel_1's MouseListener can now reference the SpriteField and call a method which can produce a change...
panel_1.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Click");
panel.setColor(Color.BLUE);
}
});
Three
You need some way to tell the sprite what color it should be...
This one depends on what it is you want to achieve...
If you want to paint ALL the sprites the same color, then you need some way to tell the sprites which color they should use, for example, you could change the DrawSprite method to accept a Color parameter...
public class RoundSprite {
//...
void DrawSprite(Graphics2D g2, Color color) {
And within the SpriteField paintComponent, pass the color to the sprite
public class SpriteField extends JPanel {
//...
private Color color = Color.BLACK;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
AffineTransform tOldTransform = g2.getTransform();
for (RoundSprite tOne : mSprites) {
tOne.DrawSprite(g2, color);
}
g2.setTransform(tOldTransform);
}
Now, this will paint ALL the sprites within the field the same color, if you want to change the color of individual sprites, this comes infinitely more complicated...
Lets leave aside the issues of selecting a sprite for the moment...
Basically, you would need to apply the same principle from point Two to the RoundSprite class.
You would need to supply a method that could set/get the desired color. You would need to store this value in an instance field of the RoundSprite class and when DrawSprite is called, apply that Color to the Graphics context.
This would mean that SpriteField won't need to perform any color management, beyond passing the request for change from a caller to the selected sprite, so it would still need a setColor method...
Side Notes...
You might like to have a read through Code Conventions for the Java TM Programming Language, it will make it easier for people to read your code and for you to read others
Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify
Oh, and you realise that there already is a JButton class that probably should be used instead of a JPanel with a MouseListener....?
I am working on a keylistener exercise for my java class, but have been stuck for the past week. I appreciate any helpful suggestions. The exercise is:
"Write a program that draws line segments using the arrow keys. The
line starts from the center of the frame and draws toward east, north,
west, or south when the right-arrow key, up-arrow key, left-arrow key,
or down-arrow key is clicked."
Through debugging I figured out that the KeyListener works to the point
of getting to drawComponent(Graphics g), but it only draws when I press
down or right and that only works the first couple times. Here is my code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class EventProgrammingExercise8 extends JFrame {
JPanel contentPane;
LinePanel lines;
public static final int SIZE_OF_FRAME = 500;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
EventProgrammingExercise8 frame = new EventProgrammingExercise8();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public EventProgrammingExercise8() {
setTitle("EventExercise8");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(SIZE_OF_FRAME, SIZE_OF_FRAME);
contentPane = new JPanel();
lines = new LinePanel();
contentPane.add(lines);
setContentPane(contentPane);
contentPane.setOpaque(true);
lines.setOpaque(true);
lines.setFocusable(true);
lines.addKeyListener(new ArrowListener());
}
private class LinePanel extends JPanel {
private int x;
private int y;
private int x2;
private int y2;
public LinePanel() {
x = getWidth() / 2;
y = getHeight() / 2;
x2 = x;
y2 = y;
}
protected void paintComponent(Graphics g) {
g.drawLine(x, y, x2, y2);
x = x2;
y = y2;
}
public void drawEast() {
x2 += 5;
repaint();
}
public void drawWest() {
x2 -= 5;
repaint();
}
public void drawNorth() {
y2 -= 5;
repaint();
}
public void drawSouth() {
y2 += 5;
repaint();
}
}
private class ArrowListener extends KeyAdapter {
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_RIGHT) {
lines.drawEast();
} else if (key == KeyEvent.VK_LEFT) {
lines.drawWest();
} else if (key == KeyEvent.VK_UP) {
lines.drawNorth();
} else {
lines.drawSouth();
}
}
}
}
Thanks.
A few things jump out at me...
public LinePanel() {
x = getWidth() / 2;
y = getHeight() / 2;
This will be an issue, because at the time you construct the class, it's size is 0x0
Apart from the fact that you haven't called super.paintComponent which breaks the paint chain, you seem to think that painting is accumaltive...
protected void paintComponent(Graphics g) {
g.drawLine(x, y, x2, y2);
x = x2;
y = y2;
}
Painting in Swing is destructive. That is, you are expected to erase to the Graphics context and rebuild the output from scratch. The job paintComponent is to clear the Graphics context ready for painting, but you've not called super.paintComponent, breaking the paint chain and opening yourself up to a number of very ugly paint artifacts
Calling setSize(SIZE_OF_FRAME, SIZE_OF_FRAME); on a frame is dangerous, as it makes no guarantee about the frames border insets, which will reduce the viewable area available to you.
This....
contentPane = new JPanel();
lines = new LinePanel();
contentPane.add(lines);
setContentPane(contentPane);
Is not required, it just adds clutter to your code. It's also a good hint as to what is going wrong with your code.
JPanel uses a FlowLayout by default. A FlowLayout uses the component's preferred size to determine how best to layout the components. The default preferred size of a component is 0x0
You could use...
lines = new LinePanel();
add(lines);
instead or set the contentPane to use a BorderLayout which will help...
Try adding lines.setBorder(new LineBorder(Color.RED)); add see what you get...
Oddly, during my testing, your KeyListener worked fine...
Basically...
Override the getPreferredSize method of the LinePanel and return the size of the panel you would like to use.
Use a java.util.List to maintain a list of Points that need to be painted.
In you paintComponent method, use the Point List to actually render you lines. This will be a bit tricky, as you need two points and the List may contain an odd number of points, but's doable.
Calculate the start Point either by using the preferred size or some other means (like using a ComponentListener and monitoring the componentResized method. This becomes tricky as your component may be resized a number of times when it is first created and released to the screen and you will want to ignore future events once you have your first point)